当DP遇见Py(三) -- 装饰模式

目录
  1. 定义:
  2. 类图:
  3. 类型:结构型
  4. 实例:
    1. C++ 实现
    2. Python 实现
    3. Pythonic 实现
    4. 运行结果
  5. Tips:
    1. 装饰器

定义:

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

类图:

类型:结构型

实例:

给“小菜”一件一件穿衣服

C++ 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <string>
#include <iostream>
using namespace std;

class Person
{
private:
string name;
public:
Person(string name)
{
this->name = name;
}
Person(){}
virtual void show()
{

cout<<"装扮的是:" << name << endl;
}
};

class Finery:public Person
{
protected:
Person *component;
public:
void decorate(Person* component)
{

this->component = component;
}
virtual void show()
{

component->show();
}
};

class TShirts:public Finery
{
public:
virtual void show()
{

component->show();
cout << "T shirts" << endl;
}
};

class BigTrouser:public Finery
{
public:
virtual void show()
{

component->show();
cout << "Big Trouser" << endl;
}
};

int main()
{

Person *p = new Person("小菜");
BigTrouser *bt = new BigTrouser();
TShirts *ts = new TShirts();

bt->decorate(p);
ts->decorate(bt);
ts->show();

return 0;
}

Python 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# -*- coding=utf-8 -*-

class Person(object):
def __init__(self, name):
self.name = name

def show(self):
print '装扮的是:%s' % self.name

class Finery(Person):
def __init__(self):
self.component = None

def decorate(self, component):
self.component = component

def show(self):
self.component.show()

class TShirts(Finery):
def show(self):
self.component.show()
print 'T shirts'

class BigTrouser(Finery):
def show(self):
self.component.show()
print 'Big Trouser'

if __name__ == '__main__':
p = Person('小菜')
bt = BigTrouser()
ts = TShirts()

bt.decorate(p)
ts.decorate(bt)
ts.show()

Pythonic 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# -*- coding=utf-8 -*-
from functools import wraps

def dress(clothes):
def wrapped(fn):
@wraps(fn)
def _wrapped(*args):
fn(*args)
print clothes
return _wrapped
return wrapped

@dress('T shirts')
@dress('Big Trouser')
def finery(name):
print '装扮的是: %s' % name

if __name__ == '__main__':
finery('小菜')

运行结果

1
2
3
装扮的是:小菜
Big Trouser
T shirts

Tips:

装饰器

Python的修饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西。但是,他们要干的事都很相似——都是想要对一个已有的模块做一些“修饰工作”。Python 的 Decorator使用很简单,就是在方法名前面加一个@XXX注解来为这个方法装饰一些东西。对于Python的这个@注解语法糖- Syntactic Sugar 来说,当你在用某个@decorator来修饰某个函数func时,如下所示:

1
2
3
@decorator
def func():
pass

Python解释器会解释成下面这样的语句:

1
func = decorator(func)

看看上面的语法,这其实就是把一个函数当参数传到另一个函数中,然后再回调!是的,但是,我们需要注意,这里还有一个赋值语句,把decorator这个函数的返回值赋值回了原来的func。
这个语法是不是似曾相识,是的,在当DP遇见Py(二)中就有他的身影——高阶函数闭包
就我们上面那个例子来说,

1
2
3
4
@dress('T shirts')
@dress('Big Trouser')
def finery(name):
print '装扮的是: %s' % name

被解释成了:

1
finery = dress('T shirts')(dress('Big Trouser')(finery))

Python的Decorator就是这么简单,没有什么复杂的东西,你也不需要了解过多的东西,使用起来就是那么自然、简洁。

评论